﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MacomberMapSystem.Common.Internals
{
    /// <summary>
    /// This class provides an interface for a collection of CIM elements that are sorted by 
    /// </summary>
    public class MM_CIM_SortedCollection : IEnumerable<KeyValuePair<String, String>>
    {
        #region Variable declarations
        /// <summary>Our internal list of attributes</summary>
        private List<KeyValuePair<String, String>> Attributes;

        /// <summary>Whether our attributes are currently sorted</summary>
        private bool Sorted = true;

        /// <summary>Our element comparer</summary>
        private MM_CIM_Comparer Comparer = new MM_CIM_Comparer();

        /// <summary>Our comparison method</summary>
        private StringComparison ComparisonMethod;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize a new CIM sorted collection
        /// </summary>
        public MM_CIM_SortedCollection()
        {
            Attributes = new List<KeyValuePair<string, string>>();
            ComparisonMethod = StringComparison.CurrentCultureIgnoreCase;
        }

        /// <summary>
        /// Initialize a new CIM sorted collection
        /// </summary>
        /// <param name="Capacity">The capacity of our collection</param>
        public MM_CIM_SortedCollection(int Capacity)
        {
            Attributes = new List<KeyValuePair<string, string>>(Capacity);
            ComparisonMethod = StringComparison.CurrentCultureIgnoreCase;
        }

        /// <summary>
        /// Initialize a new CIM sorted collection
        /// </summary>
        /// <param name="Capacity">The capacity of our collection</param>
        /// <param name="ComparisonMethod">The comparison method for strings</param>
        public MM_CIM_SortedCollection(int Capacity, StringComparison ComparisonMethod)
        {
            Attributes = new List<KeyValuePair<string, string>>(Capacity);
            this.ComparisonMethod = ComparisonMethod;
        }


        /// <summary>
        /// Initialize a new CIM sorted collection
        /// </summary>
        /// <param name="ComparisonMethod">The comparison method for strings</param>
        public MM_CIM_SortedCollection(StringComparison ComparisonMethod)
        {
            this.ComparisonMethod = ComparisonMethod;
        }
        #endregion

        #region Element addition/deletion
        /// <summary>
        /// Add a new element to our collection
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Value"></param>
        public void Add(String Name, String Value)
        {
            KeyValuePair<String, String> NewKVP = new KeyValuePair<string, string>(Name, Value);
            if (Sorted && Attributes.Count != 0 && Comparer.Compare(NewKVP, Attributes[Attributes.Count-1]) != 1)
                Sorted = false;
            Attributes.Add(NewKVP);
        }

        /// <summary>
        /// Add the contents of a second collectino to the first
        /// </summary>
        /// <param name="Collection"></param>
        public void AddRange(MM_CIM_SortedCollection Collection)
        {
            List<KeyValuePair<String, String>> AttributesToAdd = new List<KeyValuePair<string, string>>();
            foreach (KeyValuePair<String, String> kvp in Collection.Attributes)
            {
                if (Sorted && Attributes.Count != 0 && Comparer.Compare(kvp, Attributes[Attributes.Count - 1]) != -1)
                    Sorted = false;
                AttributesToAdd.Add(kvp);
            }

            Attributes.AddRange(AttributesToAdd);
        }

        /// <summary>
        /// Remove a range of key/value pairs from the collection
        /// </summary>
        /// <param name="Collection"></param>
        public void RemoveRange(MM_CIM_SortedCollection Collection)
        {
            foreach (KeyValuePair<String, String> kvp in Collection.Attributes)
                Remove(kvp.Key, kvp.Value);
        }
        /// <summary>
        /// Determine whether an element is in our collection 
        /// </summary>
        /// <param name="Name"></param>
        /// <returns></returns>
        public bool Contains(String Name)
        {
            foreach (KeyValuePair<String, String> kvp in Attributes)
                if (String.Equals(kvp.Key, Name, ComparisonMethod))
                    return true;
            return false;
        }

        /// <summary>
        /// Determine whether an element is in our collection
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public bool Contains(String Name, String Value)
        {
            foreach (KeyValuePair<String, String> kvp in Attributes)
                if (String.Equals(kvp.Key, Name, ComparisonMethod) && String.Equals(kvp.Value, Value, ComparisonMethod))
                    return true;
            return false;
        }

        /// <summary>
        /// Remove any instances of the specified element
        /// </summary>
        /// <param name="Name"></param>
        public int Remove(String Name)
        {
            int CurPos = 0;
            int Removed = 0;
            while (CurPos < Attributes.Count)
                if (Attributes[CurPos].Key.Equals(Name))
                {
                    Attributes.RemoveAt(CurPos);
                    Removed++;
                }
                else
                    CurPos++;
            return Removed;
        }

        /// <summary>        
        /// Remove any instances of the specified element
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Value"></param>
        public int Remove(String Name, String Value)
        {
            int CurPos = 0;
            int Removed = 0;
            while (CurPos < Attributes.Count)
                if (Attributes[CurPos].Key.Equals(Name) && Attributes[CurPos].Value.Equals(Value))
                {
                    Attributes.RemoveAt(CurPos);
                    Removed++;
                }
                else
                    CurPos++;
            return Removed;
        }

        
        #endregion

        #region Sorting and processing
        /// <summary>
        /// Sort our elements as needed
        /// </summary>
        /// <param name="ComparisonMethod">The comparison method</param>
        public void Sort(StringComparison ComparisonMethod)
        {
            Comparer.ComparisonMethod = ComparisonMethod;
            if (!Sorted)
                Attributes.Sort(Comparer);
            Sorted = true;
        }

        /// <summary>
        /// Return an enumerator for parsing through our sorted collection
        /// </summary>
        /// <returns></returns>
        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
        {
            Sort(ComparisonMethod);
            return Attributes.GetEnumerator();
        }

         /// <summary>
        /// Return an enumerator for parsing through our sorted collection
        /// </summary>
        /// <returns></returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            Sort(ComparisonMethod);
            return Attributes.GetEnumerator();
        }
        #endregion


        #region Comparer class
        /// <summary>
        /// This class provides a comparer between elements
        /// </summary>
        private class MM_CIM_Comparer : IComparer<KeyValuePair<String, String>>
        {

            public StringComparison ComparisonMethod = StringComparison.CurrentCultureIgnoreCase;

            /// <summary>
            /// Compare two key/value pair strings
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
            {
                String X = x.Key.Substring(x.Key.IndexOf(':') + 1);
                String Y = y.Key.Substring(x.Key.IndexOf(':') + 1);

                int Comp = String.Compare(X, Y, ComparisonMethod);
                if (Comp != 0)
                    return Comp;
                else
                    return String.Compare(x.Value, y.Value, ComparisonMethod);
            }
        #endregion
        }


     

    }
}